##########################################################################
##########################################################################
#####                                                                #####
#####     VMAI/N03 r1p0  (c) Copyright Matthew F. Rienzo, 2014       #####
#####                                                                #####
#####  - Conceptualized November 3rd, 2014.  (N03)                   #####
#####  - Revision 1 (Original) patch 0 (unpatched)                   #####
#####                                                                #####
#####             Copyright Matthew F. Rienzo, 2014                  #####
#####                                                                #####
#####  - Virtual machine bro                                         #####
##########################################################################
##########################################################################

use strict;
use warnings;
use Data::Dumper;

use SDL;
use SDLx::App;
use SDLx::Text;
use SDL::Event;
use SDL::Events;

#  VMAI
#  Copyright Matthew F. Rienzo, 2014
  
#  VMAI N03 r1p0

my $DBG = 0;
my $SDLDBG = 0;
my $__vmRingMode = 0;

# Hash table
my $__VM_HT = {
  __VM_Registry => {
    CurrentProc => 'VMAI',
    PROCESSOR_ARCH => 'WI100',
    MACHINE_GENERATION => 'N03',
    MACHINE_VERSION => 'r1p0',
	PROCESSOR_GEN => 'WI10X',
	SDL_ENABLE => 0xFFFFFF,
	WIN32_API => 0x000000,
	BIOSBINARY => './BIOS_IMAGE/wibios.vm',
	FULLSCREEN => 1,
	__vmX => 0,
	__vmY => 0,
	function_guts => ' ',
  },
};

#{
$__VM_HT->{__VM_Registry}->{msg} = SDLx::Text->new(
  x => $__VM_HT->{__VM_Registry}->{__vmX},
  y => $__VM_HT->{__VM_Registry}->{__vmY},
  font  => 'pf_arma_five.ttf',
  size  => 14,
  color => 0xffffff,
);
#}

# Variables
my $__VM_VARS = {
  'NULL' => 0,
};

# Register opcodes
my $_RegsOpcode = {
  "\x00" => "i0",
  "\x01" => "i1",
  "\x02" => "i2",
  "\x03" => "i3",
  "\x04" => "i4",
  "\x05" => "i5",
  "\x06" => "i6",
  "\x07" => "i7",
  "\x08" => "i8",
  "\x09" => "i9",
  "\xA0" => "a0",
  "\xA1" => "a1",
  "\xA2" => "a2",
  "\xA3" => "a3",
  "\xA4" => "a4",
  "\xA5" => "a5",
  "\xA6" => "a6",
  "\xA7" => "a7",
  "\xA8" => "a8",
  "\xA9" => "a9",
  "\xB0" => "s0",
  "\xB1" => "s1",
  "\xB2" => "s2",
  "\xB3" => "s3",
  "\xB4" => "s4",
  "\xB5" => "s5",
  "\xB6" => "s6",
  "\xB7" => "s7",
  "\xB8" => "s8",
  "\xB9" => "s9",
  "\xC0" => "r0",
  "\xC1" => "r1",
  "\xC2" => "r2",
  "\xC3" => "r3",
  "\xC4" => "r4",
  "\xC5" => "r5",
  "\xC6" => "r6",
  "\xC7" => "r7",
  "\xC8" => "r8",
  "\xC9" => "r9",
  "\xD0" => "f0",
  "\xD1" => "f1",
  "\xD2" => "f2",
  "\xD3" => "f3",
  "\xD4" => "f4",
  "\xD5" => "f5",
  "\xD6" => "f6",
  "\xD7" => "f7",
  "\xD8" => "f8",
  "\xD9" => "f9",
};
  
# Registers (this is a long one!)
my $__VM_REGS = {
  'r0' => 0,
  'r1' => 0,
  'r2' => 0,
  'r3' => 0,
  'r4' => 0,
  'r5' => 0,
  'r6' => 0,
  'r7' => 0,
  'r8' => 0,
  'r9' => 0,
  's0' => 0,
  's1' => 0,
  's2' => 0,
  's3' => 0,
  's4' => 0,
  's5' => 0,
  's6' => 0,
  's7' => 0,
  's8' => 0,
  's9' => 0,
  'a0' => 0,
  'a1' => 0,
  'a2' => 0,
  'a3' => 0,
  'a4' => 0,
  'a5' => 0,
  'a6' => 0,
  'a7' => 0,
  'a8' => 0,
  'a9' => 0,
  'f0' => 0,
  'f1' => 0,
  'f2' => 0,
  'f3' => 0,
  'f4' => 0,
  'f5' => 0,
  'f6' => 0,
  'f7' => 0,
  'f8' => 0,
  'f9' => 0,
  'i0' => 0,
  'i1' => 0,
  'i2' => 0,
  'i3' => 0,
  'i4' => 0,
  'i5' => 0,
  'i6' => 0,
  'i7' => 0,
  'i8' => 0,
  'i9' => 0,
};

# $__VM_STACK->{0}->{a0} = $__VM_REGS->{a0}; $__VM_REGS->{a0} = 0;
#  == push0 %a0
my $__VM_STACK = { };
# This is for the halt/RSOD
use constant {
  SAFE_HALT      => 0,
  UF_MACH_ERR    => -1,
  BAD_BITCODE    => -2,
  CORRUPT_BINARY => -3,
  NO_BIOS        => -4,
  BAD_BIT_SIZE   => -5,
  BAD_REG        => -6,
  NO_SUCH_VAR    => -7,
  FAKE_SAFE_HALT => 1,
};

#my $#__vmX = 0;
#my $#__vmY = 0;

#{ ARGV
my $__VM_ARGC = 0;
for($__VM_ARGC = 0; $ARGV[$__VM_ARGC]; $__VM_ARGC++){
  if($ARGV[$__VM_ARGC] eq "--debug"){
    $DBG = 1;
  }elsif($ARGV[$__VM_ARGC] eq "--test"){
    $__VM_HT->{__VM_Registry}->{BIOSBINARY} = "./dev_test".$ARGV[$__VM_ARGC+1].".vm";
	$__VM_ARGC += 1;
  }elsif($ARGV[$__VM_ARGC] eq "--test2"){
    $__VM_HT->{__VM_Registry}->{BIOSBINARY} = "./dev_test2.vm";
  }elsif($ARGV[$__VM_ARGC] eq "--boot"){
	$__VM_HT->{__VM_Registry}->{BOOTBINARY} = $ARGV[$__VM_ARGC+1];
	$__VM_ARGC += 1;
  }elsif($ARGV[$__VM_ARGC] eq "--boot-conf"){
    $__VM_HT->{__VM_Registry}->{BOOTCONF} = $ARGV[$__VM_ARGC+1];
	$__VM_ARGC += 1;
  }elsif($ARGV[$__VM_ARGC] eq "--no-fullscreen"){
    $__VM_HT->{__VM_Registry}->{FULLSCREEN} = 0;
  }elsif($ARGV[$__VM_ARGC] eq "--vt100"){
    $__VM_HT->{__VM_Registry}->{WIN32_API} = 0xFFFFFF;
  }
}
#}

if($__VM_HT->{__VM_Registry}->{WIN32_API} == 0xFFFFFF){  
# Use VT100 colors because SDL is broken
  eval("use Win32::Console::ANSI;");
}

#{ TE
print "\e[2J\e[31mVMAI [...] Copyright Matthew Rienzo, 2014\n";
print "VMAI [Creating SDL window] ...\n";
print "VMAI [RING:0]\n";
#}

if($__VM_HT->{__VM_Registry}->{SDL_ENABLE} == 0x000000){
  print "                \e[32mFAILED: SDL_ENABLE = ".$__VM_HT->{__VM_Registry}->{SDL_ENABLE}."\e[31m\n";
}

if($__VM_HT->{__VM_Registry}->{FULLSCREEN} == 0){
  SDL::putenv("SDL_VIDEO_WINDOW_POS=0,0");
}

#{ TE
my $__VM_SDL_SCREEN = SDLx::App->new(
  width => 800,  # can also do 1024x600
  height => 600,
  depth => 16,
  title => 'VMAI N03 r1p0',
  exit_on_quit => 1,
  fullscreen => $__VM_HT->{__VM_Registry}->{FULLSCREEN},
);


$__VM_SDL_SCREEN->add_event_handler(\&quit_event);
$__VM_SDL_SCREEN->add_event_handler(\&do_key);
#$__VM_SDL_SCREEN->fullscreen();
#}

# $__INT
my $__INT = {
  "0x00" => sub{	
    if($__vmRingMode == 1 || $__vmRingMode == 3){
	  quit(SAFE_HALT);
	}
	
	$__VM_STACK->{"0x00"}->{s0} = -1;
	return -1;
  },
  "0x03" => sub{
    # in push0x03 %a0 is the ring number
    if($__vmRingMode == 1 || $__vmRingMode == 3){
      my $nowIn = $__VM_STACK->{"0x03"}->{a0};
	  $__VM_STACK->{"0x03"}->{a0} = 0;
	 
	  $__vmRingMode = $nowIn;
	  
	  $__VM_STACK->{"0x03"}->{s0} = 0;
	  return 0;
    }
   
    $__VM_STACK->{"0x03"}->{s0} = -1;
    return 0;
  },
};

sub quit{
  my $r = shift;
  my $controller = $__VM_SDL_SCREEN;
  
  if($r == SAFE_HALT){
    print "\nSAFE_HALT\n\e[31mVMAI [Moving to RING:2]\n";
	
	$__vmRingMode = 2;
	my $a = SDLx::Text->new(
	  x => 0,
	  y => 565,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffffff,
	);
	
    my $d = SDLx::Text->new(
	  x => 350,
	  y => 45,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffff00,
	);
	
	$controller->draw_rect([ 0, 0, $controller->width, $controller->height, ], 0x8b0000ff);
	$d->write_to($controller, "VM halted!");
	$controller->update();
	$d->y(60);
	$d->write_to($controller, "Exiting [...]");
	$controller->update();
	$a->write_to($controller, "VMAI/N03 r1p0, or Virtual Machine Application Interface, concept N03, revision 1, patched 0 times.");  
	$controller->update();
	$a->y(580);
	$a->write_to($controller, "Product name: VMAI/N03.  Copyright (c) Matthew F. Rienzo, 2014");
	$controller->update();
	
	sleep(3);
	
    $controller->stop();
	
	
    print "VMAI [\e[33mHALTED\e[31m]\e[0m";
    exit($r);
  }elsif($r == UF_MACH_ERR){
    my $oldRing = $__vmRingMode;
	
	print "\e[31mVMAI [\e[33mUF_MACH_ERR ($r)\e[31m]\n -- Encountered error in RING:$oldRing\n";
	print "\e[31mVMAI [Moving to RING:2]\n";
	
	$__vmRingMode = 2;
	my $a = SDLx::Text->new(
	  x => 0,
	  y => 0,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffffff,
	);
	
    my $d = SDLx::Text->new(
	  x => 200,
	  y => 245,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffff00,
	);
	
	$controller->draw_rect([ 0, 0, $controller->width, $controller->height, ], 0x8b0000ff);
	$a->write_to($controller, "Error in RING:$oldRing");
	$controller->update();
	$a->y(15);
	$a->write_to($controller, "Now in RING:$__vmRingMode");
	$controller->update();
	$a->y(30);
	$a->write_to($controller, "<Press the escape key to exit>");
	$controller->update();
	
	# The error message:
	#  VMAI/N03 (r1p0) has encountered a fatal error!
	#  :--  RING:$oldRing
	#  :--  ERR: UF_MACH_ERR
	#  VM operation has ceased.
	
	$d->write_to($controller, "VMAI/N03 (r1p0) has encountered a fatal error!");
	$controller->update();
	$d->y(260);
	$d->write_to($controller, ":--  RING:$oldRing");
	$controller->update();
	$d->y(275);
	$d->write_to($controller, ":--  ERR: UF_MACH_ERR ($r)");
	$controller->update();
	$d->y(290);
	$d->write_to($controller, "VM operation has ceased.");
	
	$controller->update();
	
	return 0;
  }elsif($r == BAD_BITCODE){
    my $oldRing = $__vmRingMode;
	
	print "VMAI [\e[33mBAD_BITCODE ($r)\e[31m]\n -- Encountered error in RING:$oldRing\n";
	print "\e[31mVMAI [Moving to RING:2]\n";
	
	$__vmRingMode = 2;
	my $a = SDLx::Text->new(
	  x => 0,
	  y => 0,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffffff,
	);
	
    my $d = SDLx::Text->new(
	  x => 200,
	  y => 245,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffff00,
	);
	
	$controller->draw_rect([ 0, 0, $controller->width, $controller->height, ], 0x8b0000ff);
	$a->write_to($controller, "Error in RING:$oldRing");
	$controller->update();
	$a->y(15);
	$a->write_to($controller, "Now in RING:$__vmRingMode");
	$controller->update();
	$a->y(30);
	$a->write_to($controller, "<Press the escape key to exit>");
	$controller->update();
	
	# The error message:
	#  VMAI/N03 (r1p0) has encountered a fatal error!
	#  :--  RING:$oldRing
	#  :--  ERR: BAD_BITCODE
	#  VM operation has ceased.
	
	$d->write_to($controller, "VMAI/N03 (r1p0) has encountered a fatal error!");
	$controller->update();
	$d->y(260);
	$d->write_to($controller, ":--  RING:$oldRing");
	$controller->update();
	$d->y(275);
	$d->write_to($controller, ":--  ERR: BAD_BITCODE ($r)");
	$controller->update();
	$d->y(290);
	$d->write_to($controller, "VM operation has ceased.");
	
	$controller->update();
	
	return 0;
  }elsif($r == CORRUPT_BINARY){
    my $oldRing = $__vmRingMode;
	
	print "\e[31mVMAI [\e[33mCORRUPT_BINARY ($r)\e[31m]\n -- Encountered error in RING:$oldRing\n";
	print "\e[31mVMAI [Moving to RING:2]\n";
	
	$__vmRingMode = 2;
	my $a = SDLx::Text->new(
	  x => 0,
	  y => 0,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffffff,
	);
	
    my $d = SDLx::Text->new(
	  x => 200,
	  y => 245,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffff00,
	);
	
	$controller->draw_rect([ 0, 0, $controller->width, $controller->height, ], 0x8b0000ff);
	$a->write_to($controller, "Error in RING:$oldRing");
	$controller->update();
	$a->y(15);
	$a->write_to($controller, "Now in RING:$__vmRingMode");
	$controller->update();
	$a->y(30);
	$a->write_to($controller, "<Press the escape key to exit>");
	$controller->update();
	
	# The error message:
	#  VMAI/N03 (r1p0) has encountered a fatal error!
	#  :--  RING:$oldRing
	#  :--  ERR: CORRUPT_BINARY
	#  VM operation has ceased.
	
	$d->write_to($controller, "VMAI/N03 (r1p0) has encountered a fatal error!");
	$controller->update();
	$d->y(260);
	$d->write_to($controller, ":--  RING:$oldRing");
	$controller->update();
	$d->y(275);
	$d->write_to($controller, ":--  ERR: CORRUPT_BINARY ($r)");
	$controller->update();
	$d->y(290);
	$d->write_to($controller, "VM operation has ceased.");
	
	$controller->update();
	
	return 0;
  }elsif($r == NO_BIOS){
    my $oldRing = $__vmRingMode;
	
	print "\e[31mVMAI [\e[33mNO_BIOS ($r)\e[31m]\n -- Encountered error in RING:$oldRing\n".
	  " -- Couldn't open the specified BIOS binary at:\n".
	  " --  \e[33m".$__VM_HT->{__VM_Registry}->{BIOSBINARY}."\e[31m\n";
	print "\e[31mVMAI [Moving to RING:2]\n";
	
	$__vmRingMode = 2;
	my $a = SDLx::Text->new(
	  x => 0,
	  y => 0,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffffff,
	);
	
    my $d = SDLx::Text->new(
	  x => 200,
	  y => 245,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffff00,
	);
	
	$controller->draw_rect([ 0, 0, $controller->width, $controller->height, ], 0x8b0000ff);
	$a->write_to($controller, "Error in RING:$oldRing");
	$controller->update();
	$a->y(15);
	$a->write_to($controller, "Now in RING:$__vmRingMode");
	$controller->update();
	$a->y(30);
	$a->write_to($controller, "<Press the escape key to exit>");
	$controller->update();
	
	# The error message:
	#  VMAI/N03 (r1p0) has encountered a fatal error!
	#  :--  RING:$oldRing
	#  :--  ERR: NO_BIOS
	#  The virtual machine couldn't load the BIOS binary at:
	#  :--  $__VM_HT{__VM_Registry}{BIOSBINARY}
	#  VM operation has ceased.
	
	
	$d->write_to($controller, "VMAI/N03 (r1p0) has encountered a fatal error!");
	$controller->update();
	$d->y(260);
	$d->write_to($controller, ":--  RING:$oldRing");
	$controller->update();
	$d->y(275);
	$d->write_to($controller, ":--  ERR: NO_BIOS ($r)");
	$controller->update();
	$d->y(290);
	$d->write_to($controller, "The virtual machine couldn't load the BIOS binary at:");
	$controller->update();
	$d->y(305);
	$d->write_to($controller, ":-- ".$__VM_HT->{__VM_Registry}->{BIOSBINARY});
	$controller->update();
	$d->y(320);
	$d->write_to($controller, "VM operation has ceased.");
	
	$controller->update();
	
	return 0;
  }elsif($r == BAD_BIT_SIZE){
    my $oldRing = $__vmRingMode;
	
	print "\e[31mVMAI [\e[33mBAD_BIT_SIZE ($r)\e[31m]\n -- Encountered error in RING:$oldRing\n";
	print "\e[31mVMAI [Moving to RING:2]\n";
	
	$__vmRingMode = 2;
	my $a = SDLx::Text->new(
	  x => 0,
	  y => 0,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffffff,
	);
	
    my $d = SDLx::Text->new(
	  x => 200,
	  y => 245,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffff00,
	);
	
	$controller->draw_rect([ 0, 0, $controller->width, $controller->height, ], 0x8b0000ff);
	$a->write_to($controller, "Error in RING:$oldRing");
	$controller->update();
	$a->y(15);
	$a->write_to($controller, "Now in RING:$__vmRingMode");
	$controller->update();
	$a->y(30);
	$a->write_to($controller, "<Press the escape key to exit>");
	$controller->update();
	
	# The error message:
	#  VMAI/N03 (r1p0) has encountered a fatal error!
	#  :--  RING:$oldRing
	#  :--  ERR: BAD_BIT_SIZE ($r)
	#  VM operation has ceased.
	
	
	$d->write_to($controller, "VMAI/N03 (r1p0) has encountered a fatal error!");
	$controller->update();
	$d->y(260);
	$d->write_to($controller, ":--  RING:$oldRing");
	$controller->update();
	$d->y(275);
	$d->write_to($controller, ":--  ERR: BAD_BIT_SIZE ($r)");
	$controller->update();
	$d->y(290);
	$d->write_to($controller, "VM operation has ceased.");
	
	$controller->update();
	
	return 0;
  }elsif($r == BAD_REG){
    my $oldRing = $__vmRingMode;
	
	print "\e[31mVMAI [\e[33mBAD_REG ($r)\e[31m]\n -- Encountered error in RING:$oldRing\n";
	print "\e[31mVMAI [Moving to RING:2]\n";
	
	$__vmRingMode = 2;
	my $a = SDLx::Text->new(
	  x => 0,
	  y => 0,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffffff,
	);
	
    my $d = SDLx::Text->new(
	  x => 200,
	  y => 245,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffff00,
	);
	
	$controller->draw_rect([ 0, 0, $controller->width, $controller->height, ], 0x8b0000ff);
	$a->write_to($controller, "Error in RING:$oldRing");
	$controller->update();
	$a->y(15);
	$a->write_to($controller, "Now in RING:$__vmRingMode");
	$controller->update();
	$a->y(30);
	$a->write_to($controller, "<Press the escape key to exit>");
	$controller->update();
	
	# The error message:
	#  VMAI/N03 (r1p0) has encountered a fatal error!
	#  :--  RING:$oldRing
	#  :--  ERR: BAD_REG ($r)
	#  VM operation has ceased.
	
	$d->write_to($controller, "VMAI/N03 (r1p0) has encountered a fatal error!");
	$controller->update();
	$d->y(260);
	$d->write_to($controller, ":--  RING:$oldRing");
	$controller->update();
	$d->y(275);
	$d->write_to($controller, ":--  ERR: BAD_REG ($r)");
	$controller->update();
	$d->y(290);
	$d->write_to($controller, "VM operation has ceased.");
	
	$controller->update();
	
	return 0;
  }elsif($r == NO_SUCH_VAR){
    my $oldRing = $__vmRingMode;
	
	print "\e[31mVMAI [\e[33mNO_SUCH_VAR ($r)\e[31m]\n -- Encountered error in RING:$oldRing\n";
	print "\e[31mVMAI [Moving to RING:2]\n";
	
	$__vmRingMode = 2;
	my $a = SDLx::Text->new(
	  x => 0,
	  y => 0,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffffff,
	);
	
    my $d = SDLx::Text->new(
	  x => 200,
	  y => 245,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffff00,
	);
	
	$controller->draw_rect([ 0, 0, $controller->width, $controller->height, ], 0x8b0000ff);
	$a->write_to($controller, "Error in RING:$oldRing");
	$controller->update();
	$a->y(15);
	$a->write_to($controller, "Now in RING:$__vmRingMode");
	$controller->update();
	$a->y(30);
	$a->write_to($controller, "<Press the escape key to exit>");
	$controller->update();
	
	# The error message:
	#  VMAI/N03 (r1p0) has encountered a fatal error!
	#  :--  RING:$oldRing
	#  :--  ERR: NO_SUCH_VAR ($r)
	#  VM operation has ceased.
	
	$d->write_to($controller, "VMAI/N03 (r1p0) has encountered a fatal error!");
	$controller->update();
	$d->y(260);
	$d->write_to($controller, ":--  RING:$oldRing");
	$controller->update();
	$d->y(275);
	$d->write_to($controller, ":--  ERR: NO_SUCH_VAR ($r)");
	$controller->update();
	$d->y(290);
	$d->write_to($controller, "VM operation has ceased.");
	
	$controller->update();
	
	return 0;
  }elsif($r == FAKE_SAFE_HALT){
    print "\nSAFE_HALT\n\e[31mVMAI [Moving to RING:2]\n";
	
	$__vmRingMode = 2;
	my $a = SDLx::Text->new(
	  x => 0,
	  y => 565,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffffff,
	);
	
    my $d = SDLx::Text->new(
	  x => 350,
	  y => 45,
	  font => 'pf_arma_five.ttf',
	  size => 14,
	  color => 0xffff00,
	);
	
	$controller->draw_rect([ 0, 0, $controller->width, $controller->height, ], 0x8b0000ff);
	$d->write_to($controller, "VM halted!");
	$controller->update();
	$d->y(60);
	$d->write_to($controller, "Exiting [...]");
	$controller->update();
	$a->write_to($controller, "VMAI/N03 r1p0, or Virtual Machine Application Interface, concept N03, revision 1, patched 0 times.");  
	$controller->update();
	$a->y(585);
	$a->write_to($controller, "Product name: VMAI/N03.  Copyright (c) Matthew F. Rienzo, 2014");
	$controller->update();
	
	return 0;
  }
}

sub do_key {
  my $event = shift;
  
  my $controller = shift;
  
  if($event->type == SDL_KEYDOWN && $event->key_sym == SDLK_ESCAPE && $__vmRingMode == 0){
    print "VMAI \e[33m -- Caught shutdown signal.\e[31m\n"; 
	print "VMAI [SDLK_ESCAPE]\n";
	print "VMAI [RING:0]\n";
	
	quit(SAFE_HALT);
  }elsif($event->type == SDL_KEYDOWN && $event->key_sym == SDLK_SPACE && $__vmRingMode == 0){
    $__vmRingMode = 1; # BIOS loading and execution
    main($controller);
  }elsif($event->type == SDL_KEYDOWN && $event->key_sym == SDLK_ESCAPE && $__vmRingMode == 2){
    print "VMAI \e[33m -- Caught shutdown signal.\e[31m\n"; 
	print "VMAI [SDLK_ESCAPE]\n";
	print "VMAI [Moving to RING:0]\n";
	
	$__vmRingMode = 0;
	
	quit(SAFE_HALT);
  }elsif($event->type == SDL_KEYDOWN && $event->key_sym == SDLK_1 && $__vmRingMode == 0){
    quit(UF_MACH_ERR);
  }elsif($event->type == SDL_KEYDOWN && $event->key_sym == SDLK_2 && $__vmRingMode == 0){
    quit(BAD_BITCODE);
  }elsif($event->type == SDL_KEYDOWN && $event->key_sym == SDLK_3 && $__vmRingMode == 0){
    quit(BAD_BIT_SIZE);
  }elsif($event->type == SDL_KEYDOWN && $event->key_sym == SDLK_4 && $__vmRingMode == 0){
    quit(BAD_REG);
  }elsif($event->type == SDL_KEYDOWN && $event->key_sym == SDLK_5 && $__vmRingMode == 0){
    quit(NO_BIOS);
  }elsif($event->type == SDL_KEYDOWN && $event->key_sym == SDLK_6 && $__vmRingMode == 0){
    quit(NO_SUCH_VAR);
  }elsif($event->type == SDL_KEYDOWN && $event->key_sym == SDLK_7 && $__vmRingMode == 0){
    quit(CORRUPT_BINARY);
  }elsif($event->type == SDL_KEYDOWN && $event->key_sym == SDLK_8 && $__vmRingMode == 0){
    quit(FAKE_SAFE_HALT);
  }
}

sub holdIt{
  print "\e[31mVMAI [Moving to RING:3]\n";
  $__vmRingMode = 3;
  
  my $wait = <>;
  
  return 0;
}

sub quit_event{
  my $event = shift;

  my $controller = shift;

  if($event->type == SDL_QUIT){
    print "VMAI [Caught SDL_QUIT signal]\n";
	$controller->stop();
	quit(0);
  }
}

#{    This is fo' my text editor collapse  
my $white = 0xFFFFFF;
my $black = 0x000000;
my $red = 0xFF0000;
my $green = 0x00FF00;
my $blue = 0x0000FF;
my $w_msg = SDLx::Text->new(
  x => 0,
  y => 0,
  font  => 'pf_arma_five.ttf',
  size  => 14,
  color => 0xffffff,
);

my $r_msg = SDLx::Text->new(
  x => 205,
  y => 225,
  font => 'pf_arma_five.ttf',
  size => 76,
  color => $red,
);

$__VM_SDL_SCREEN->draw_rect([ 0, 0, $__VM_SDL_SCREEN->width, $__VM_SDL_SCREEN->height, ], 0x000000ff);
$__VM_SDL_SCREEN->update();

$r_msg->write_to($__VM_SDL_SCREEN, "VMAI/N03");
$__VM_SDL_SCREEN->update();
$w_msg->write_to($__VM_SDL_SCREEN, "VMAI N03 r1p0");
$__VM_SDL_SCREEN->update();
$w_msg->x(755);
$w_msg->write_to($__VM_SDL_SCREEN, $__VM_HT->{__VM_Registry}->{PROCESSOR_ARCH});
$__VM_SDL_SCREEN->update();
$w_msg->x(770);
$w_msg->y(15);
$w_msg->write_to($__VM_SDL_SCREEN, $__VM_HT->{__VM_Registry}->{MACHINE_GENERATION});
$__VM_SDL_SCREEN->update();
$w_msg->x(0);
$w_msg->write_to($__VM_SDL_SCREEN, "Virtual Machine, processor WI100.");
$__VM_SDL_SCREEN->update();
$w_msg->y(30);
$w_msg->write_to($__VM_SDL_SCREEN, "Copyright Matthew Rienzo, 2014");
$__VM_SDL_SCREEN->update();
$w_msg->y(45);
$w_msg->write_to($__VM_SDL_SCREEN, "<http://code.google.com/p/vmai/>");
$__VM_SDL_SCREEN->update();
$w_msg->y(315);
$w_msg->x(280);
$w_msg->write_to($__VM_SDL_SCREEN, "<Press the spacebar to continue>"); 
$__VM_SDL_SCREEN->update();
$w_msg->y(330);
$w_msg->x(290);
$w_msg->write_to($__VM_SDL_SCREEN, "<Press the escape key to exit>");
$__VM_SDL_SCREEN->update();

$__VM_SDL_SCREEN->run();
#}

sub main{
  my $app = shift;
  
  # This is so that main() can't be called from an RSOD screen.
  # At some point there should be a __VM_HT var that decides whether the VM RSODs or
  # if to give the error to a handler defined by the OS so the OS can decide whether to RSOD or not
  # otherwise, if the OS loads a bad binary, it could crash the whole machine.
  
  my $mainInBIOS = 0;
  my $mainInKernel = 0;
  my $mainInUserSpace = 0;
  
  
  # Functions
  ## Maybe new lines (\n) can be caught by a function in the OS that splits the string into an array
  ## @str = ( 0 => $number of lines, 1 => $line1, 2..n => $line2..n, );  And the puts() function takes an array
  ## with the line index in @[0] and the lines in @[1..0].  The parent function, such as print($) should also count
  ## the maximum characters that will fit on the screen in this font (pf_arma_five), and break each string
  ## into a new line at 1 char short, so we can word wrap.  But that all gets to come in the OS ;)
  ## ~~ programmer who doesn't want to program that into the VM (it should be done in the VASM anyway).
  
  my $__VM_FUNCTIONS = {
    vm_7614t => sub{
	  my ($vars, $regs, $ht, $funcs, $SCREEN) = @_;
	  
	  # User space programs cannot use this function!
	  if($__vmRingMode == 4) { 
	    return ($vars, $regs, $ht);
	  }
	  
	  if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }else{$__VM_HT->{__VM_Registry}->{__vmY} += 15;}
	  
	  #print ($DBG ? "_f_vmY = ".$__VM_HT->{__VM_Registry}->{__vmY}."\n" : "");
	  
	  $ht->{__VM_Registry}->{msg}->y($__VM_HT->{__VM_Registry}->{__vmY});
	  $ht->{__VM_Registry}->{msg}->write_to($__VM_SDL_SCREEN, $regs->{a0});
	  $__VM_SDL_SCREEN->update();
	  
	  print "\e[33m".$regs->{a0}."\e[31m\n";
	  
	  return ($vars, $regs, $ht);
	},
	vm_9922t => sub {  # This function will be comment'd out of the production release!
	  my ($vars, $regs, $ht, $funs, $SCREEN) = @_;
	  # This function crashes the system.  It is just an exit(-1) with a console message.
	  # vm_9922t(void);
	  # call vm_9922t
	  # ..and the heartbeat of this VM process will flat line.
	  
	  # User space programs cannot use this function!
	  if($__vmRingMode == 4) { 
	    return ($vars, $regs, $ht);
	  }
	  
	  print "\e[33m<> vm_9922t was called!\n".
        "\e[36mHello USER,\n    I am the virtual machine.  A special developer function was executed inside of me".
        " and now I'm gonna quit.  That's right.  I'm not gonna save memory, work, or even show you that \"VM HALTED\" screen!"." \e[33mGood bye.\e[0m";
	
	  exit(-1);
    },
  };
  
  
  if($__vmRingMode == 1){
    $mainInBIOS = 1;
  }elsif($__vmRingMode == 3){
    $mainInKernel = 1;
  }elsif($__vmRingMode == 4){
    $mainInUserSpace = 1;
  }else{
    return 0;
  }
  
  while(1){
    if($mainInKernel == 1){
      # Remember we have to load [HEADER], [VARS], [LINKLIST] and [CODE]
	  # and [HEADER] and [LINK] for VLL!
	  
	  # We aren't here yet!!
	  quit(UF_MACH_ERR);
	  return 0;
    }
    elsif($mainInBIOS == 1){
      $SDLDBG = 1;
	
      $__VM_HT->{__VM_Registry}->{__vmX} = 0;
      $__VM_HT->{__VM_Registry}->{__vmY} = 0;
	
      my $msg = SDLx::Text->new(
        x => 0,
        y => 580,
        font  => 'pf_arma_five.ttf',
        size  => 14,
        color => 0xffffff,
      );
    
      $app->draw_rect([280, 315, 250, 31], 0x000000ff);
      $app->update();
    
      $msg->write_to($app, "Loading BIOS...");
      $app->update();
      my $masterInt = 0x000000;

	  sleep(1);
	
	  # Clear screen for SDLDBG
	  $app->draw_rect([0, 0, 800, 600], 0x000000ff);
	  $msg->x(0);
	  $msg->y(0);
	
	  $msg->write_to($app, "Loading ".$__VM_HT->{ __VM_Registry}->{BIOSBINARY}." into buffer...");
	  $app->update();
	
      # read binary
	  my $success = 0;
      my $buffer;
	  open FILE, $__VM_HT->{__VM_Registry}->{BIOSBINARY} or $success = -1;
	  if($success == -1){
        quit(NO_BIOS);
	    return -1;
	  }
	
      while(<FILE>){
        $buffer .= $_;
      }
	  close FILE;
	
	  $msg->y(15);
	  $msg->write_to($app, "Loading BIOS [HEADER]...");
	  $app->update();

	  $__VM_HT->{__VM_Registry}->{__vmY} = 30;
      # Load the header of the bios:
      ($masterInt) = &processHeader($masterInt, $buffer, $app);
    
	  ($masterInt == -1 ? return -1 : nothing());
	
	  if(($__VM_HT->{__VM_Registry}->{__vmY}+15) > 585) {
	    #cls
	    $app->draw_rect([0, 0, 800, 600], 0x000000ff);
	    $__VM_HT->{__VM_Registry}->{__vmY} = 0;
	  }
	
	  $msg->y($__VM_HT->{__VM_Registry}->{__vmY});
	  $msg->write_to($app, "Loading BIOS [VARS]...");
	  $app->update();
	
	  $__VM_HT->{__VM_Registry}->{__vmY} += 15;
      # Load the variables
 	
      ($masterInt, $__VM_VARS) = &processVars($masterInt,  $buffer, $__VM_VARS, $app);
    
	  ($masterInt == -1 ? return -1 : nothing());
		
	  if(($__VM_HT->{__VM_Registry}->{__vmY}+15) > 585){
        #cls
	    $app->draw_rect([0, 0, 800, 600], 0x000000ff);
	    $__VM_HT->{__VM_Registry}->{__vmY} = 0;
	  }
	
	  $msg->y($__VM_HT->{__VM_Registry}->{__vmY});
	  $msg->write_to($app, "Loading BIOS [CODE]...");
	  $app->update();
	
	  $__VM_HT->{__VM_Registry}->{__vmY} += 15;
      # Load the code section
      ($masterInt, $__VM_VARS, $__VM_REGS, $__VM_HT, $__VM_FUNCTIONS) = &codeExe($masterInt, $buffer, $__VM_VARS, $__VM_REGS, $__VM_HT, $__VM_FUNCTIONS, $_RegsOpcode, $app);
	
	  ($masterInt == -1? return -1 : nothing());
	
	  if(($__VM_HT->{__VM_Registry}->{__vmY}+15) > 585) {
	    #cls
	    $app->draw_rect([0, 0, 800, 600], 0x000000ff);
	    $__VM_HT->{__VM_Registry}->{__vmY} = 0;
	  }

	  $msg->y($__VM_HT->{__VM_Registry}->{__vmY});
	  $msg->write_to($app, "Jumping to __##BIOS##__main...");
	  $app->update();
	
	  $__VM_HT->{__VM_Registry}->{__vmY} += 15;
	  
	  $__VM_HT->{__VM_Registry}->{msg}->x($__VM_HT->{__VM_Registry}->{__vmX});
	  $__VM_HT->{__VM_Registry}->{msg}->y($__VM_HT->{__VM_Registry}->{__vmY});
	  
	  # call the main function in the BIOS
      ($masterInt, $__VM_VARS, $__VM_REGS, $__VM_HT) = $__VM_FUNCTIONS->{__entry}($__VM_VARS, $__VM_REGS, $__VM_HT, $__VM_FUNCTIONS); warn $@ if $@;
	  
	  sleep(10);
	
      $mainInBIOS = 0;
	  
	  print "\e[31mVMAI [Moving to RING:3]\n";
	  
      $__vmRingMode = 3; # Kernel space
      $mainInKernel = 1;	  
    }
  }
  if($mainInBIOS == 1){
    $mainInBIOS = 0;
  }elsif($mainInKernel == 1){
    $mainInKernel = 0;
  }
	
  return 0;
}

sub cls{
  my $app = shift;
  
  $__VM_SDL_SCREEN->draw_rect([0, 0, 800, 600], 0x000000ff);

  $__VM_HT->{__VM_Registry}->{__vmX} = 0;
  $__VM_HT->{__VM_Registry}->{__vmY} = 0;
  
  return 0;
}

sub processHeader{
  my ($n, $binary, $app) = @_;
  
  $__VM_HT->{__VM_Registry}->{__vmY} = 30;
  
  my $msg = SDLx::Text->new(
    x => $__VM_HT->{__VM_Registry}->{__vmX},
    y => $__VM_HT->{__VM_Registry}->{__vmY},
    font  => 'pf_arma_five.ttf',
    size  => 14,
    color => 0xffffff,
  );
    
  my $instr = substr($binary, $n, 2);
  
  if($instr eq "\xFF\xFF"){
    if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY}); $msg->write_to($app, "VMAI -- Found [HEADER] section [0xFFFF]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
    print ($DBG ? " - found header opcode\n" : "");
    
    $n = 2;
    
    $instr = substr($binary, $n, 1);
    
    if($instr eq "\x00"){
	  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found bits opcode [0x00]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	  if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
      print ($DBG ? " - found bits opcode\n" : "");
      $n = 3;
      $instr = substr($binary, $n, 1);
      if($instr eq "\x20"){ # 32 bits
	    if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Binary is formatted at 32 bits [0x20]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	    if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
        $instr = "32";
        $n = 4;
      }else{
	    print ($DBG ? "\n == \$n = $n\n" : "");
	    quit(BAD_BIT_SIZE, $app);
		return -1;
      }
    }else{
	  print ($DBG ? "\n == \$n = $n\n" : "");
	  quit(BAD_BITCODE, $app);
	  return -1;
    }
    
    $instr = substr($binary, $n, 2);  # 16 bit operand
    if($instr eq "\xEF\xEF"){
	  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found end of header [0xEFEF]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	  if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
      print ($DBG ? "<span class=notice> - found .end</span>\n" : "");
      $n = 6;
    }else{
	  print ($DBG ? "\n == \$n = $n\n" : "");
	  quit(CORRUPT_BINARY, $app);
	  return -1;
    }
    
  }
  return ($n);
}

#    /* Now we should be in the vars section */
#    /* F0F0F0E0 */
  
sub processVars{
  my ($n, $binary, $vars, $app) = @_;
  
  my $msg = SDLx::Text->new(
    x => $__VM_HT->{__VM_Registry}->{__vmX},
    y => $__VM_HT->{__VM_Registry}->{__vmY},
    font  => 'pf_arma_five.ttf',
    size  => 14,
    color => 0xffffff,
  );
  
  my $instr = substr($binary, $n, 4); # 32 bit operand
  if($instr eq "\xF0\xF0\xF0\xE0"){ # [VARS]
    if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found [VARS] section [0xF0F0F0E0]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
	  
    print ($DBG ? "<span class=notice> - found [VARS]</span>\n" : "");
    $n = 10;
 
    $instr = substr($binary, $n, 4); # 32 bits
    $n = 14;
      
    while(1){
      if($instr eq "\x00\x00\x00\x00"){ # Delimiter
        if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found variable delimiter [0x00000000]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
        if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
        print ($DBG ? "<span class=notice> - found variable delim</span>\n" : "");
        $instr = substr($binary, $n, 1); # 8 bits
        $n += 1;
          
	    if($instr eq "\xA0"){ # Variable name
          print ($DBG ? "<span class=notice> - found variable name</span>\n" : "");
          my $varname = substr($binary, $n, index(substr($binary, $n), "\xA0"));
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found variable [$varname]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - VARNAME: $varname</span>\n" : "");
          $n = $n + length($varname) + 1;
          
          $n += 4;
           
          $instr = substr($binary, $n, 1);

          if($instr eq "\xA0"){ # Var value
		    if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found variable value [$varname]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	        if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
            print ($DBG ? "<span class=notice> - found variable value</span>\n" : "");
            $n += 1;
            $vars->{$varname} = substr($binary, $n, index(substr($binary, $n), "\xA0"));
            print ($DBG ? "<span class=notice> -   $varname = ".$vars->{$varname}."</span>\n" : "");
            $n += (length($vars->{$varname}) + 1);
          }else{
		    print ($DBG ? "\n == \$n = $n\n" : "");
	        quit(BAD_BITCODE, $app);
		  
	        return (-1, $vars);
          }
        }else{
		  print ($DBG ? "\n == \$n = $n\n" : "");
          quit(BAD_BITCODE, $app);
	      return (-1, $vars);
        }
      }elsif($instr eq "\xE0\xF0\xE0\xF0"){
	    if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found end of section [0xE0F0E0F0]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	    if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
        print ($DBG ? "<span class=notice> - found .end</span>\n" : "");
        last;
      }else{
	    print ($DBG ? "\n == \$n = $n\n" : "");
        quit(BAD_BITCODE, $app);
        return (-1, $vars);
      }
		
      $instr = substr($binary, $n, 4);  ## 32 bit opcode
      $n += 4;
    }
  }

  return ($n, $vars);
}
    
# Code section
# F0F0F0D0

sub codeExe{
  my ($n, $binary, $vars, $regs, $ht, $functions, $_vmRegsOpcode, $app) = @_;

  my $msg = SDLx::Text->new(
    x => $__VM_HT->{__VM_Registry}->{__vmX},
    y => $__VM_HT->{__VM_Registry}->{__vmY},
    font  => 'pf_arma_five.ttf',
    size  => 14,
    color => 0xffffff,
  );
  
  my $instr = substr($binary, $n, 4); # 32 bits
  

  my $inCMP = 0;
  
  if($instr eq "\xF0\xF0\xF0\xD0"){ # Making sure we're in the CODE section
    if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found [CODE] section [0xF0F0F0D0]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
    print ($DBG ? " - found [CODE]\n" : "");
	$n += 4;
while(1){
	$instr = substr($binary, $n, 1); # 8 bit opcode

	my $function_name;
	my $function_guts = "";
	my $isEntry = 0;
	
    if($instr eq "\xF0"){  # Found a function
	  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found entry point [0xF0]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	  if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
      print ($DBG ? " - found the entry point\n" : "");
      $n += 4;
      
	  $instr = substr($binary, $n, 1); # 8 bit opcode
	
	  if($instr eq "\xA0"){
	    $n += 1;
	    $function_name = substr($binary, $n, index(substr($binary, $n), "\xA0"));
		print ($DBG ? " -- function_name=$function_name\n == \$n = $n" : "");
		
		if($function_name eq "__entry"){
		  $isEntry = 1;
		}else{
		  $isEntry = 0;
		}
	  }else{
	    print ($DBG ? " == BAD_FUNC\n" : "");
	    quit(BAD_BITCODE);
		return -1;
      }
	  
	  $n += length($function_name) + 1;
	  print ($DBG ? " == \$n = $n" : "");
	  
	  #$functions->{'__entry'} = sub
	  #  my ($vars, $regs, $ht, $funcs) = @_;
	  #  # loadd %a0 "Hello, world!"
	  #  # call __##BIOS##__println
	  #  # free %a0
	  #  # halt
	  #  # .stop
	  #  
	  #  my $function_guts = '$regs->{a0} = "Hello, world!";\n'.
	  #    '($vars, $regs, $ht) = $funcs->{"__##BIOS##__println"}($vars, $regs, $ht, $funcs, );\n'.
	  #    '$regs->{a0} = 0x000000;\n'.
	  #    'quit(SAFE_HALT, );\n'.
	  #    '##STOP##';
	  #
	  #  eval($function_guts);
	  #
	  #  return ($vars, $regs, $ht);
	  #;
	  
      $instr = substr($binary, $n, 1); # 8 bit opcode
      while(1){
        if($instr eq "\x00"){ #halt
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found halt [0x00000000]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found halt opcode</span>\n" : "");
          $n += 4; # 32 bits
		  $function_guts .= "quit(SAFE_HALT);\n";
        }
		elsif($instr eq "\x10"){  #loadi
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found loadi [0x10]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found loadi opcode</span>\n" : "");
          $n += 1;
          $instr = substr($binary, $n, 1); # 8 bit opcode for the integer register
            
          if(defined $_vmRegsOpcode->{$instr}){
			  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- [".$_vmRegsOpcode->{$instr}."]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	          if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
              print ($DBG ? "<span class=notice> -  register ".$_vmRegsOpcode->{$instr}."</span>\n" : "");
              
			  my $variable = $instr;
			  $n += 1;
			  $instr = substr($binary, $n, 1); # 8 bit delimiter
			  
			  if($instr eq "\xA0"){
                print ($DBG ? "<span class=notice> - found integer value</span>\n" : "");
                $n += 1;
				$function_guts .= '$regs->{'.$_vmRegsOpcode->{$variable}.'} = '.substr($binary, $n, index(substr($binary, $n), "\xA0")).";\n";
                $regs->{$_vmRegsOpcode->{$variable}} = substr($binary, $n, index(substr($binary, $n), "\xA0"));
				if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- [".$_vmRegsOpcode->{$variable}." => ".$regs->{$_vmRegsOpcode->{$variable}}."]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	            if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
                print ($DBG ? "<span class=notice> - integer = ".$regs->{$_vmRegsOpcode->{$variable}}."</span>\n" : "");
                $n += (length($regs->{$_vmRegsOpcode->{$variable}}) + 1);
              }
			  else{
			    print ($DBG ? " == \$n = $n\n" : "");
			    quit(BAD_BITCODE, $app);
				return (-1);
              } 
            }
			else{
			  print ($DBG ? " == \$n = $n\n" : "");
			  quit(BAD_REG, $app);
			  return -1;
            }
        }
		elsif($instr eq "\x1A"){  #loadd
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found loadd [0x1A]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found loadd opcode</span>\n" : "");
          $n += 1;
          $instr = substr($binary, $n, 1); # 8 bit opcode for the integer register
            
          if(defined $_vmRegsOpcode->{$instr}){
			  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- [".$_vmRegsOpcode->{$instr}."]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	          if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
              print ($DBG ? "<span class=notice> -  register ".$_vmRegsOpcode->{$instr}."</span>\n" : "");
              
			  my $variable = $instr;
			  $n += 1;
			  $instr = substr($binary, $n, 1); # 8 bit delimiter
			  
			  if($instr eq "\xA0"){
                print ($DBG ? "<span class=notice> - found value</span>\n" : "");
                $n += 1;
				$function_guts .= '$regs->{'.$_vmRegsOpcode->{$variable}.'} = '.substr($binary, $n, index(substr($binary, $n), "\xA0")).";\n";
                $regs->{$_vmRegsOpcode->{$variable}} = substr($binary, $n, index(substr($binary, $n), "\xA0"));
                $n += (length($regs->{$_vmRegsOpcode->{$variable}}) + 1);
              }
			  else{
			    print ($DBG ? " == \$n = $n\n" : "");
			    quit(BAD_BITCODE, $app);
				return (-1);
              } 
            }
			else{
			  print ($DBG ? " == \$n = $n\n" : "");
			  quit(BAD_REG, $app);
			  return -1;
            }
        }
		elsif($instr eq "\x20"){  # add
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found add [0x20]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found add opcode</span>\n" : "");
            
          $n += 1;
          $instr = substr($binary, $n, 1); # 8 bit for register
            
          if(defined $_vmRegsOpcode->{$instr}){
		    if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- [".$_vmRegsOpcode->{$instr}."]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	        if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
            print ($DBG ? "<span class=notice> -  register ".$_vmRegsOpcode->{$instr}."</span>\n" : "");
            $n += 1;
              
            my $reg1 = substr($binary, $n, 1); # 8 bit for register
            if(defined $_vmRegsOpcode->{$reg1}){
			  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- [".$_vmRegsOpcode->{$reg1}."]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	          if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
              print ($DBG ? "<span class=notice> -  register ".$_vmRegsOpcode->{$reg1}."</span>\n" : "");
              $n += 1;
              
              my $reg2 = substr($binary, $n, 1); # 8 bit for register
              if(defined $_vmRegsOpcode->{$reg2}){
			    if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- [".$_vmRegsOpcode->{$reg2}."]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	            if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
                print ($DBG ? "<span class=notice> - register ".$_vmRegsOpcode->{$reg2}."</span>\n" : "");
			    $function_guts .= '$regs->{'.$_vmRegsOpcode->{$instr}.'} = ($regs->{'.
			      $_vmRegsOpcode->{$reg1}.'} + $regs->{'.$_vmRegsOpcode->{$reg2}."});\n";
                $regs->{$_vmRegsOpcode->{$instr}} = ($regs->{$_vmRegsOpcode->{$reg1}} + $regs->{$_vmRegsOpcode->{$reg2}});
                  
                $n += 1; # 8 bit opcode
              }
			  else{
			    print ($DBG ? " == \$n = $n\n" : "");
			    quit(BAD_REG, $app);
			    return -1;
              }
		    }
			else{
			  print ($DBG ? " == \$n = $n\n" : "");
			  quit(BAD_REG, $app);
			  return -1;
            }
          }
		  else{
		    print ($DBG ? " == \$n = $n\n" : "");
		    quit(BAD_REG, $app);
			return -1;
          }
        }
		elsif($instr eq "\x03"){ # mov
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found mov [0x03]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found mov opcode</span>\n" : "");
            
          $n += 2;
          $instr = substr($binary, $n, 1); # 8 bit opcode for register
           
          if(defined $_vmRegsOpcode->{$instr}){
		    if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- [".$_vmRegsOpcode->{$instr}."]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	        if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
			print ($DBG ? "<span class=notice> -  register ".$_vmRegsOpcode->{$instr}."</span>\n" : "");
              
            $n += 1;
            my $reg1 = substr($binary, $n, 1); # 8 bit opcode for register
              
            if(defined $_vmRegsOpcode->{$reg1}){
			  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- [".$_vmRegsOpcode->{$reg1}."]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	          if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
              print ($DBG ? "<span class=notice> -  register ".$_vmRegsOpcode->{$reg1}."</span>\n" : "");
              
			  $function_guts .= '$regs->{'.$_vmRegsOpcode->{$instr}.'} = $regs->{'.$_vmRegsOpcode->{$reg1}."};\n";
				
              $regs->{$_vmRegsOpcode->{$instr}} = $regs->{$_vmRegsOpcode->{$reg1}};
                
              $n += 1;
            }
			else{
			  print ($DBG ? " == \$n = $n\n" : "");
			  quit(BAD_REG, $app);
			  return -1;
            }
          }
		  else{
		    print ($DBG ? " == \$n = $n\n" : "");
			quit(BAD_REG, $app);
			return -1;
	      }
        }
		elsif($instr eq "\x40"){ # call
		  print "[A]";
			
          if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found call [0x40]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - call opcode</span>\n" : "");
            
          $n += 4;
          $instr = substr($binary, $n, 1); # 8 bit opcode
           
          if($instr eq "\xA0"){
			print "[B]";
            $n += 1;
            my $funcname = substr($binary, $n, index(substr($binary, $n), "\xA0"));
            $n += length($funcname) + 1;
              
			if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Function [$funcname]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	        if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
            print ($DBG ? "<span class=notice> -  funcname = $funcname</span>\n" : "");
             
			$function_guts .= '($vars, $regs, $ht) = $funcs->{"'.$funcname.'"}($vars, $regs, $ht, $funcs, );'."\n";
          }
	      else{
		    print ($DBG ? " == \$n = $n\n" : "");
			quit(BAD_BITCODE, $app);
			return -1;
          }
        }
		  elsif($instr eq "\x04"){ # movv
		    if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found movv [0x04]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	        if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
            print ($DBG ? "<span class=notice> - movv opcode</span>\n" : "");
            
            $n += 3;
            my $reg = substr($binary, $n, 1);
            
            if(defined $_vmRegsOpcode->{$reg}){
			  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- [".$_vmRegsOpcode->{$reg}."]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	          if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
              print ($DBG ? "<span class=notice> -  register ".$_vmRegsOpcode->{$reg}."</span>\n" : "");
              $n += 1;
              $instr = substr($binary, $n, 1);
              
              if($instr eq "\xA0"){
                $n += 1;
                my $varname = substr($binary, $n, index(substr($binary, $n), "\xA0"));
                $n += length($varname) + 1;
                
				if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Variable [$varname]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	            if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
                print ($DBG ? "<span class=notice> -  varname = $varname</span>\n" : "");
				
                if(defined $vars->{$varname}){
				  $function_guts .= '$regs->{'.$_vmRegsOpcode->{$reg}.'} = $vars->{"'.$varname.'"};'."\n";
				  
                  $regs->{$_vmRegsOpcode->{$reg}} = $vars->{$varname};
                }
				else{
				  print ($DBG ? " == \$n = $n\n" : "");
				  quit(NO_SUCH_VAR, $app);
				  return -1;
                }
              }
			  else{
			    print ($DBG ? " == \$n = $n\n" : "");
			    quit(BAD_BITCODE, $app);
				return -1;
              }
            }
			else{
			  print ($DBG ? " == \$n = $n\n" : "");
			  quit(BAD_REG, $app);
			  return -1;
            }
          }
		elsif($instr eq "\xE0"){ # .stop / .end
		  $instr = substr($binary, $n, 4);
		  if($instr eq "\xE0\xe0\xe0\xe0"){ #.stop
		    if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found .stop [0xE0E0E0E0]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	        if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
            print ($DBG ? "<span class=notice> - found .stop opcode</span>\n" : "");
			
			$function_guts .= "#STOP#\n";
			
			my $CODE_PART = "sub{\n".
			  "my (\$vars, \$regs, \$ht, \$funcs) = \@_;\n".
			  "my \$empty = 0;\n".
			  $function_guts."\n";
			  
			#$functions->{$function_name} = eval("sub{".
			#  "my (\$vars, \$regs, \$ht, \$funcs) = \@_;\n".
			#  "my \$code = ".$function_guts.";\n".
			#  "eval(\$code);\n";
			  
			if($isEntry == 1){
			  $CODE_PART .= "return (\$vars, \$regs, \$ht);\n}";
			}else{
			  $CODE_PART .= "}";
			}
			
			print ($DBG ? "CODE_PART: \n$CODE_PART\n" : "");
			
			$functions->{$function_name} = eval($CODE_PART); warn "In our function [$function_name]: $@!\n" if $@;
			
			$n += 4;
			
			if($isEntry == 0){
			  last;
			}
	      }
		  elsif($instr eq "\xe0\xe0\xe0\xf0"){ #.end
		    if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found .end [0xE0E0E0F0]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	        if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
            print ($DBG ? "<span class=notice> - found .end opcode</span>\n" : "");
			
			return ($n, $vars, $regs, $ht, $functions);
		  }
		  else{
		    print ($DBG ? " == \$n = $n\n" : "");
		    quit(BAD_BITCODE, $app);
			return -1;
	      }
		}
    	elsif($instr eq "\x05"){ # _sl_ <> _end_
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found inline code [0x05]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found inline code</span>\n" : "");
		  $n+= 4;
		  
		  $instr = substr($binary, $n, 1); # 8 bit opcode
	  
	      my $inline_code = 0;
		  
	      if($instr eq "\xA0"){
	        $n += 1;
	        $inline_code = substr($binary, $n, index(substr($binary, $n), "\xA0"));
		    
            $n += length($inline_code) + 1;
          }else{
		    print ($DBG ? " == \$n = $n\n" : "");
            quit(BAD_BITCODE);
            return -1;
          }

          $function_guts .= "##_sl_##\n$inline_code\n##_end_##\n";

        }		  
		elsif($instr eq "\xFF"){ # ret
		  $n += 1;
		  $instr = substr($binary, $n, 3); # 3 bytes
		  if($instr eq "\x00\xFF\x00"){
		    if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found return [0xFF00FF00]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	        if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
            print ($DBG ? "<span class=notice> - found ret</span>\n" : "");
			
			$function_guts .= "return (\$vars, \$regs, \$ht);\n";
		  }else{
		    print ($DBG ? " == \$n = $n\n" : "");
		    quit(BAD_BITCODE);
			return -1;
		  }
		  
		  $n += 3;
		}
		elsif($instr eq "\x30"){ # free
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found free [0x30]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found free opcode</span>\n" : "");
		  $n += 3;
		  
		  $instr = substr($binary, $n, 1); # 8 bit for register
		  if(defined $_vmRegsOpcode->{$instr}){
		    $function_guts .= "\$regs->{".$_vmRegsOpcode->{$instr}."} = 0;\n";
		  }else{
		    print ($DBG ? " == \$n = $n\n" : "");
			quit(BAD_REG);
			return -1;
		  }
		  
		  $n += 1;
		}
		elsif($instr eq "\x70"){ # push[0..f]
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found push [0x70]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found push opcode</span>\n" : "");
		  
		  $n += 1;
		  
		  $instr = substr($binary, $n, 1);
		  
		  if($instr eq "\xA0"){
		    $n += 1;
			
			my $stack = substr($binary, $n, index(substr($binary, $n), "\xA0"));
			
			$n += length($stack) + 1;
			my $reg = substr($binary, $n, 1);
			
			if(defined $_vmRegsOpcode->{$reg}){
			  $function_guts .= "\$__VM_STACK->{'$stack'}->{".$_vmRegsOpcode->{$reg}."} = \$regs->{".$_vmRegsOpcode->{$reg}."};\n";
			  $function_guts .= "\$regs->{".$_vmRegsOpcode->{$reg}."} = 0;\n";
			}else{
			  print ($DBG ? "\$n = $n\n" : "");
			  quit(BAD_REG);
			  return -1;
			}
			
			$n += 1;
		  }else{
		    print ($DBG ? "\$n = $n\n" : "");
			quit(BAD_BITCODE);
			return -1;
	      }
		}
		elsif($instr eq "\x71"){ # pop[0..f]
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found pop [0x71]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found pop opcode</span>\n" : "");
		  
		  $n += 1;
		  
		  $instr = substr($binary, $n, 1);
		  
		  if($instr eq "\xA0"){
		    $n += 1;
			
			my $stack = substr($binary, $n, index(substr($binary, $n), "\xA0"));
			
			$n += length($stack) + 1;
			my $reg = substr($binary, $n, 1);
			
			if(defined $_vmRegsOpcode->{$reg}){
			  $function_guts .= "\$regs->{".$_vmRegsOpcode->{$reg}."} = \$__VM_STACK->{'$stack'}->{".$_vmRegsOpcode->{$reg}."};\n".
			    "\$__VM_STACK->{'$stack'}->{".$_vmRegsOpcode->{$reg}."} = 0;\n";
			}else{
			  print ($DBG ? "\$n = $n\n" : "");
			  quit(BAD_REG);
			  return -1;
			}
			
			$n += 1;
		  }else{
		    print ($DBG ? "\$n = $n\n" : "");
			quit(BAD_BITCODE);
			return -1;
	      }
		}
		elsif($instr eq "\x90"){ # appr
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found appr [0x90]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found appr opcode</span>\n" : "");
            
          $n += 2;
          $instr = substr($binary, $n, 1); # 8 bit opcode for register
           
          if(defined $_vmRegsOpcode->{$instr}){
		    if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- [".$_vmRegsOpcode->{$instr}."]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	        if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
			print ($DBG ? "<span class=notice> -  register ".$_vmRegsOpcode->{$instr}."</span>\n" : "");
              
            $n += 1;
            my $reg1 = substr($binary, $n, 1); # 8 bit opcode for register
              
            if(defined $_vmRegsOpcode->{$reg1}){
			  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- [".$_vmRegsOpcode->{$reg1}."]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	          if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
              print ($DBG ? "<span class=notice> -  register ".$_vmRegsOpcode->{$reg1}."</span>\n" : "");
              
			  $function_guts .= '$regs->{'.$_vmRegsOpcode->{$instr}.'} .= $regs->{'.$_vmRegsOpcode->{$reg1}."};\n";
				
              $regs->{$_vmRegsOpcode->{$instr}} .= $regs->{$_vmRegsOpcode->{$reg1}};
                
              $n += 1;
            }
			else{
			  print ($DBG ? " == \$n = $n\n" : "");
			  quit(BAD_REG, $app);
			  return -1;
            }
          }
		  else{
		    print ($DBG ? " == \$n = $n\n" : "");
			quit(BAD_REG, $app);
			return -1;
	      }
        }
		elsif($instr eq "\x91"){  # app
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found app [0x91]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found app opcode</span>\n" : "");
          $n += 1;
          $instr = substr($binary, $n, 1); # 8 bit opcode for the integer register
            
          if(defined $_vmRegsOpcode->{$instr}){
			  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- [".$_vmRegsOpcode->{$instr}."]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	          if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
              print ($DBG ? "<span class=notice> -  register ".$_vmRegsOpcode->{$instr}."</span>\n" : "");
              
			  my $variable = $instr;
			  $n += 1;
			  $instr = substr($binary, $n, 1); # 8 bit delimiter
			  
			  if($instr eq "\xA0"){
                print ($DBG ? "<span class=notice> - found value</span>\n" : "");
                $n += 1;
				$function_guts .= '$regs->{'.$_vmRegsOpcode->{$variable}.'} .= '.substr($binary, $n, index(substr($binary, $n), "\xA0")).";\n";
                $regs->{$_vmRegsOpcode->{$variable}} .= substr($binary, $n, index(substr($binary, $n), "\xA0"));
                $n += length(substr($binary, $n, index(substr($binary, $n), "\xA0"))) + 1;
              }
			  else{
			    print ($DBG ? " == \$n = $n\n" : "");
			    quit(BAD_BITCODE, $app);
				return (-1);
              } 
            }
			else{
			  print ($DBG ? " == \$n = $n\n" : "");
			  quit(BAD_REG, $app);
			  return -1;
            }
        }
		elsif($instr eq "\x92"){  # appv
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found app [0x91]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found app opcode</span>\n" : "");
          $n += 1;
          $instr = substr($binary, $n, 1); # 8 bit opcode for the integer register
            
          if(defined $_vmRegsOpcode->{$instr}){
			  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- [".$_vmRegsOpcode->{$instr}."]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	          if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
              print ($DBG ? "<span class=notice> -  register ".$_vmRegsOpcode->{$instr}."</span>\n" : "");
              
			  my $variable = $instr;
			  $n += 1;
			  $instr = substr($binary, $n, 1); # 8 bit delimiter
			  
			  if($instr eq "\xA0"){
                print ($DBG ? "<span class=notice> - found value</span>\n" : "");
                $n += 1;
				my $varname = substr($binary, $n, index(substr($binary, $n), "\xA0"));
				
				if(defined $__VM_VARS->{$varname}){
				  $function_guts .= '$regs->{'.$_vmRegsOpcode->{$variable}."} .= \$vars->{$varname};\n";
                  $n += length($varname) + 1;
				}else{
				  print ($DBG ? " == \$n = $n\n" : "");
				  quit(NO_SUCH_VAR);
				  return -1;
				}
              }
			  else{
			    print ($DBG ? " == \$n = $n\n" : "");
			    quit(BAD_BITCODE, $app);
				return (-1);
              } 
            }
			else{
			  print ($DBG ? " == \$n = $n\n" : "");
			  quit(BAD_REG, $app);
			  return -1;
            }
        }
		elsif($instr eq "\x80"){ # cmp
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found cmp [0x80]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found cmp opcode</span>\n" : "");
		  
		  $n += 2;
		  
		  my $reg1 = substr($binary, $n, 1);
		  
		  if(!(defined $_vmRegsOpcode->{$reg1})){
		    print ($DBG ? " == \$n = $n\n" : "");
			quit(BAD_REG);
			return -1;
		  }
		  
		  $n += 1;
		  
		  my $reg2 = substr($binary, $n, 1);
		  
          if(!(defined $_vmRegsOpcode->{$reg2})){
		    print ($DBG ? " == \$n = $n\n" : "");
			quit(BAD_REG);
			return -1;
		  }
		  
		  $n += 1;
		  
		  $function_guts .= "if(\$regs->{".$_vmRegsOpcode->{$reg1}."} eq \$regs->{".$_vmRegsOpcode->{$reg2}."}){\n";
		  
		  $inCMP = 1;
		  
		
		}
        elsif($instr eq "\x81"){ # cmpf
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found cmpf [0x81]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found cmpf opcode</span>\n" : "");
          $n += 4;
 
          if($inCMP != 1){
            print ($DBG ? " == \$n = $n\n" : "");
			print ($DBG ? " Not in cmp" : "");
            quit(BAD_BITCODE);
            return -1;
          }

          $function_guts .= "else{\n";
		  
		  $inCMP = 2;
		}
		elsif($instr eq "\x08"){#scmp
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found scmp [0x08]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found scmp opcode</span>\n" : "");
		  $n += 4;
		  
		  if($inCMP == 1){
		    $function_guts .= "}\n";
		  }elsif($inCMP == 2){
		    $function_guts .= "}\n";
			$inCMP = 0;
		  }else{
		    print ($DBG ? " == \$n = $n\n" : "");
			print ($DBG ? " Not in cmp" : "");
			quit(BAD_BITCODE);
		    return -1;
		  }
		  
		}
		elsif($instr eq "\x5C"){ # int
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found int [0x5C]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found int opcode</span>\n" : "");
		  
		  $n += 4;
		  
		  $instr = substr($binary, $n, 1); # xA0
		  
		  $n += 1;
		  
		  my $int = 0;
		  
		  if($instr eq "\xA0"){
		    $int = substr($binary, $n, index(substr($binary, $n), "\xA0"));
			
			$n += length($int) + 1;
			if(defined $__INT->{"$int"}){
			  $function_guts .= "\$empty = \$__INT->{'$int'}(\$vars, \$regs, \$ht, \$funcs);\n";
			}else{
			  print ($DBG ? "-- No such IRQ\n" : "");
			  $__VM_STACK->{$int}->{s0} = -1;
			}
		  }else{
		    print ($DBG ? " == \$n = $n\n" : "");
		    quit(BAD_BITCODE, $app);
            return -1;
          }			
		}
		elsif($instr eq "\xC5"){ # set .function 0xHEX
		  if($SDLDBG == 1){ $msg->y($__VM_HT->{__VM_Registry}->{__vmY});$msg->write_to($app, "VMAI -- Found set [0xC5]"); $app->update(); $__VM_HT->{__VM_Registry}->{__vmY} += 15;  }
	      if(($__VM_HT->{__VM_Registry}->{__vmY}+15) >= 585) { $app->draw_rect([0, 0, 800, 600], 0x000000ff); $__VM_HT->{__VM_Registry}->{__vmY} = 0; }
          print ($DBG ? "<span class=notice> - found set opcode</span>\n" : "");
		
	     $n += 1;
	 	 $instr = substr($binary, $n, 1);
		 
		 $n += 1;
		 print "A";
		 if($instr eq "\xA0"){
		   print "B";
		   
		   my $intHexCode = substr($binary, $n, index(substr($binary, $n), "\xA0"));
		   
		   print "$intHexCode";
		   $n += length($intHexCode) + 1;
		
		   $n += 4;
		   
		   $instr = substr($binary, $n, 1);
		   
		   $n += 1;
		   if($instr eq "\xA0"){
		     print "C";
		     my $intFunction = substr($binary, $n, index(substr($binary, $n), "\xA0"));
			 
			 print $intFunction;
			 $__INT->{"$intHexCode"} = $functions->{"$intFunction"};
			 
			 $n += length($intFunction) + 1;
		   }
		   else{
		     print ($DBG ? " function == \$n = $n\n" : "");
			 quit(BAD_BITCODE);
			 return -1;
		   }
		 }
		 else{
		   print ($DBG ? " hexcode		   == \$n = $n\n" : "");
		   quit(BAD_BITCODE);
		   return -1;
		 }
		}
		else{
		  print ($DBG ? "infunc == \$n = $n\n" : "");
		  quit(BAD_BITCODE, $app);
		  return -1;
        }
        $instr = substr($binary, $n, 1); # 8 bit opcode
		print ($DBG ? " == \$n = $n\n" : "");
      }
    }
	else{
	    print ($DBG ? " == \$n = $n\n" : "");
	    quit(BAD_BITCODE, $app);
		return -1;
    }
    
	}
  }
  else{
    print ($DBG ? " == \$n = $n\n" : "");
    quit(CORRUPT_BINARY, $app);
	return -1;
  }
}

sub nothing{
  my $thisFunctionDoesNothingUsefulAtAll = "the number 'K'";
  
  return;
}
